package store.lunangangster.engine.impl;

import java.util.Stack;
import store.lunangangster.engine.ProcessEngineConfiguration;
import store.lunangangster.engine.impl.interceptor.CommandContext;

public class Context {

  public static final ThreadLocal<ProcessEngineConfiguration> configurationThreadLocal = new ThreadLocal<>();
  // 命令的执行通常是栈式的，所以当嵌套调用命令时，应将上层命令对应的CommandContext保存起来
  public static final ThreadLocal<Stack<CommandContext>> commandContextStackThreadLocal = new ThreadLocal<>();

  public static ProcessEngineConfiguration getProcessEngineConfiguration() {
    return configurationThreadLocal.get();
  }

  public static void setProcessEngineConfiguration(ProcessEngineConfiguration configuration) {
    configurationThreadLocal.set(configuration);
  }

  public static void removeProcessEngineConfiguration() {
    configurationThreadLocal.remove();
  }

  public static CommandContext getCommandContext() {
    Stack<CommandContext> stack = getCommandContextStack();
    return stack.isEmpty() ? null : stack.peek();
  }

  public static void setCommandContext(CommandContext commandContext) {
    Stack<CommandContext> stack = getCommandContextStack();
    stack.push(commandContext);
  }

  public static void removeCommandContext() {
    Stack<CommandContext> stack = getCommandContextStack();
    stack.pop();
  }

  private static Stack<CommandContext> getCommandContextStack() {
    Stack<CommandContext> stack = commandContextStackThreadLocal.get();
    // ThreadLocal不会出现线程安全问题
    if (stack == null) {
      stack = new Stack<>();
      commandContextStackThreadLocal.set(stack);
    }
    return stack;
  }


  public static void clearCommandContext() {
    commandContextStackThreadLocal.get().clear();
  }
}
